package com.fengye.security.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fengye.security.security.filter.RestAuthenticationFilter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
import org.springframework.security.crypto.password.MessageDigestPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.zalando.problem.spring.web.advice.security.SecurityProblemSupport;

import java.util.Collection;
import java.util.Map;

@RequiredArgsConstructor
@Slf4j
@EnableWebSecurity(debug = true)
@Order(100)
public class FormSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                // formLogin
                .formLogin(form -> form.loginPage("/login")
                        .usernameParameter("username") // 表单用户名参数
                        .passwordParameter("password") // 表单密码参数
                        .permitAll())

                // 权限控制
                .authorizeRequests(req -> {
                    req.antMatchers("/api/**").hasRole("USER");
                    req.antMatchers("/admin/**").hasRole("ADMIN");
                    req.antMatchers("/authorize/**").permitAll();
                    req.anyRequest().authenticated();
                })

                // csrf token
//                .csrf(Customizer.withDefaults())
                // 自定义下列 url 忽略 csrf 验证
                .csrf(csrf -> csrf.ignoringAntMatchers("/api/**", "/admin/**", "/authorize/**"))

                // httpBasic认证
//                .httpBasic(Customizer.withDefaults())

                // rememberMe
                .rememberMe(rememberMe ->
                        rememberMe
                                .tokenValiditySeconds(30 * 24 * 3600)
                                .rememberMeParameter("remember-meq")
                                .rememberMeCookieName("somethingToRememberMeCookie")
                )

                // logout 注销
                .logout(logout -> logout.logoutUrl("/perform_logout"))
        ;
    }


    /*
     * 处理 url 的请求不需要经过过滤器 - 用于忽略静态资源
     * @author fengyexjtu@126.com
     * @date 2022/4/12 10:00 AM
     * @param web
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/open/**");
        // 常用位置忽略安全检查
        web.ignoring().requestMatchers(PathRequest.toStaticResources().atCommonLocations());
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//        log.debug("passwordEncoder, {}", passwordEncoder().encode("12345678"));
//        log.debug("SHA-1, {}", new MessageDigestPasswordEncoder("SHA-1").encode("1234abcd"));

        auth.inMemoryAuthentication()
                .withUser("user")
                .password("{bcrypt}$2a$10$cfIcXZ/fkY4y8ZAFGMMUkOf3UTGrQ6DLRcvnOHVWw9Whjut6iSdMe")
                .roles("ADMIN", "USER")
                .and()
                .withUser("zhangsan")
                .password("{SHA-1}{x83fhu95KI54M6SWnGQxxiYteTE4FmoSCob0vfrHPRs=}12caa272cb6b4b5b082156cd45a235feb53e414a")
                .roles("USER");
    }
}